<?php
namespace Swork\Client;

use Swork\Pool\ConnectionInterface;
use Swork\Pool\ElasticSearch\ElasticSearchConnection;
use Swork\Pool\PoolCollector;
use Swork\Pool\PoolInterface;

class ElasticSearch
{
    /**
     * @var PoolInterface
     */
    private $pool;

    /**
     * 初始化获取连接池
     * Redis constructor.
     */
    public function __construct()
    {
        $this->pool = PoolCollector::getCollector(PoolCollector::ElasticSearch, 'default');
    }

    /**
     * 中文分词分析
     * @param string $word 需要检验的词
     * @param string $analyzer 分词组件名
     * @return array|mixed
     * @throws
     */
    public function analyze(string $word,string $analyzer = 'ik_smart')
    {
        $result = false;
        $conn = $this->getConnection();

        try
        {
            $result = $conn->analyze($word,$analyzer);
            if($result != false && isset($result['tokens']))
            {
                $result = $result['tokens'];
            }
        }
        catch (\Exception $ex)
        {
            throw $ex;
        }
        finally
        {
            $this->pool->releaseConnection($conn);
        }

        return $result;
    }

    /**
     * 搜索数据，搜索条件的写法：
     * @param string $index 储存库
     * @param array $query 搜索条件
     * @param string $cols 输出字段
     * @param array $sort 排序规则
     * @param int $size 页量
     * @param int $idx 页码
     * @return array|bool
     * @throws
     */
    public function search(string $index, array $query, string $cols = '*', array $sort = [], int $size = 25, int $idx = 1)
    {
        $result = false;
        $conn = $this->getConnection();

        try
        {
            $result = $conn->search($index, $query, $cols, $sort, $size, $idx);
        }
        catch (\Exception $ex)
        {
            throw $ex;
        }
        finally
        {
            $this->pool->releaseConnection($conn);
        }

        return $result;
    }

    /**
     * 创建储存库
     * @param string $index 储存库
     * @param array $properties 字段属性
     * @return bool
     * @throws
     */
    public function indexInit(string $index, array $properties)
    {
        $result = false;
        $conn = $this->getConnection();

        try
        {
            if(!$conn->indexExist($index))
            {
                $result = $conn->indexCreate($index, $properties);
            }
        }
        catch (\Exception $ex)
        {
            throw $ex;
        }
        finally
        {
            $this->pool->releaseConnection($conn);
        }

        return $result;
    }

    /**
     * 创建单个文档索引
     * @param string $index 储存库
     * @param array $values 字段内容
     * @return array|mixed
     * @throws
     */
    public function documentInsert(string $index, array $values)
    {
        $result = false;
        $conn = $this->getConnection();

        try
        {
            $result = $conn->documentInsert($index, $values);
        }
        catch (\Exception $ex)
        {
            throw $ex;
        }
        finally
        {
            $this->pool->releaseConnection($conn);
        }

        return $result;
    }

    /**
     * 通过搜索来更新文档内容
     * @param string $index 储存库
     * @param array $query 搜索条件
     * @param array $script 更新脚本内容（按painless语法）
     * @return array|mixed
     * @throws
     */
    public function documentUpdate(string $index, array $query, array $script)
    {
        $result = false;
        $conn = $this->getConnection();

        try
        {
            $result = $conn->documentUpdate($index, $query, $script);
        }
        catch (\Exception $ex)
        {
            throw $ex;
        }
        finally
        {
            $this->pool->releaseConnection($conn);
        }

        return $result;
    }

    /**
     * 通过数据ID来更新文档内容
     * @param string $index 储存库
     * @param string $id 数据ID
     * @param array $script 更新脚本内容（按painless语法）
     * @return array|mixed
     * @throws
     */
    public function documentUpdateById(string $index, string $id, array $script)
    {
        $result = false;
        $conn = $this->getConnection();

        try
        {
            $result = $conn->documentUpdateById($index, $id, $script);
        }
        catch (\Exception $ex)
        {
            throw $ex;
        }
        finally
        {
            $this->pool->releaseConnection($conn);
        }

        return $result;
    }

    /**
     * 通过数据ID来删除文档
     * @param string $index 储存库
     * @param string $id 数据ID
     * @return array|mixed
     * @throws
     */
    public function documentDeleteById(string $index, string $id)
    {
        $result = false;
        $conn = $this->getConnection();

        try
        {
            $result = $conn->documentDeleteById($index, $id);
        }
        catch (\Exception $ex)
        {
            throw $ex;
        }
        finally
        {
            $this->pool->releaseConnection($conn);
        }

        return $result;
    }

    /**
     * 通过数据ID来获取文档
     * @param string $index 储存库
     * @param string $id 数据ID
     * @param string $cols 输出字段
     * @return array|mixed
     * @throws
     */
    public function documentFetchById(string $index, string $id, string $cols = '*')
    {
        $result = false;
        $conn = $this->getConnection();

        try
        {
            $result = $conn->documentFetchById($index, $id, $cols);
        }
        catch (\Exception $ex)
        {
            throw $ex;
        }
        finally
        {
            $this->pool->releaseConnection($conn);
        }

        return $result;
    }

    /**
     * 批量操作（如同时操作创建多个文档、批量删除等）
     * @param string $index 储存库
     * @param array $params 批量操作参数
     * @return array|mixed
     * @throws
     */
    public function documentBulk(string $index, array $params)
    {
        $result = false;
        $conn = $this->getConnection();

        try
        {
            $result = $conn->documentBulk($index, $params);
        }
        catch (\Exception $ex)
        {
            throw $ex;
        }
        finally
        {
            $this->pool->releaseConnection($conn);
        }

        return $result;
    }

    /**
     * 获取连接
     * @return ElasticSearchConnection | ConnectionInterface
     */
    private function getConnection()
    {
        return $this->pool->getConnection();
    }
}
